package com.ruoyi.framework.web.service

import com.ruoyi.common.constant.CacheConstants
import com.ruoyi.common.core.domain.entity.SysUser
import com.ruoyi.common.core.redis.RedisCache
import com.ruoyi.common.exception.user.UserPasswordNotMatchException
import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException
import com.ruoyi.common.utils.SecurityUtils.matchesPassword
import com.ruoyi.framework.security.context.AuthenticationContextHolder
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import java.util.concurrent.TimeUnit

/**
 * 登录密码方法
 *
 * @author ruoyi
 */
@Component
class SysPasswordService {
    @Autowired
    private lateinit var redisCache: RedisCache

    @Value(value = "\${user.password.maxRetryCount}")
    private val maxRetryCount = 0

    @Value(value = "\${user.password.lockTime}")
    private val lockTime = 0

    /**
     * 登录账户密码错误次数缓存键名
     *
     * @param username 用户名
     * @return 缓存键key
     */
    private fun getCacheKey(username: String?): String {
        return CacheConstants.PWD_ERR_CNT_KEY + username
    }

    fun validate(user: SysUser?) {
        val usernamePasswordAuthenticationToken = AuthenticationContextHolder.context
        val username = usernamePasswordAuthenticationToken.name
        val password = usernamePasswordAuthenticationToken.credentials.toString()
        var retryCount = redisCache.getCacheObject<Int>(getCacheKey(username))
        if (retryCount == null) {
            retryCount = 0
        }
        if (retryCount >= Integer.valueOf(maxRetryCount)) {
            throw UserPasswordRetryLimitExceedException(maxRetryCount, lockTime)
        }
        if (!matches(user, password)) {
            retryCount += 1
            redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES)
            throw UserPasswordNotMatchException()
        } else {
            clearLoginRecordCache(username)
        }
    }

    fun matches(user: SysUser?, rawPassword: String?): Boolean {
        return matchesPassword(rawPassword, user!!.password)
    }

    fun clearLoginRecordCache(loginName: String?) {
        if (redisCache.hasKey(getCacheKey(loginName))) {
            redisCache.deleteObject(getCacheKey(loginName))
        }
    }
}
